/*
 * =========================================================================
 *
 *       Filename:  BufferManager.h
 *
 *    Description:  �����շ�����������
 *
 *        Version:  1.0
 *        Created:  2012-01-15 22:56:04
 *  Last Modified:  2012-01-15 22:56:04
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Shi Wei (sw), shiwei2012@gmail.com
 *        Company:  NDSL UESTC
 *
 * =========================================================================
 */

#ifndef BUFFER_H_
#define BUFFER_H_

#include <cstring>
#include <sys/uio.h>
#include <sys/types.h>

#include "common/comm/BaseReq.h"
#include "common/comm/SocketAddress.h"
#include "common/comm/Reader.h"
#include "common/comm/Writer.h"
#include "common/comm/ReadCallback.h"
#include "common/comm/WriteCallback.h"
#include "common/comm/AppProtoSpec.h"

/**
 * @brief ���������ģ������ݿ���Դ��
 */
struct DataContext
{
    DataContext() {}

    virtual ~DataContext() {}
};

/**
 * @brief д�����������ݿ�
 */
struct Iov
{
    Iov()
    {
        m_pContext = NULL;
        m_pCompleteBuffer = NULL;
        memset(&m_Iovec, 0, sizeof(m_Iovec));
    }

    Iov(char *pBuf, size_t len, DataContext *pContext = NULL)
    {
        m_pCompleteBuffer = pBuf;
        m_Iovec.iov_base = pBuf;
        m_Iovec.iov_len = len;
        m_pContext = pContext;
    }
    Iov(char *pBuf,
        size_t len,
        SocketAddress &addr,
        DataContext *pContext = NULL)
    {
        m_pCompleteBuffer = pBuf;
        m_Iovec.iov_base = pBuf;
        m_Iovec.iov_len = len;
        m_pContext = pContext;
        addr.getAddr(m_UDPAddr);
    }
    virtual ~Iov()
    {
        m_Iovec.iov_base = NULL;
        m_Iovec.iov_len = 0;
        m_pCompleteBuffer = NULL;
        m_pContext = NULL;
        memset(&m_UDPAddr, 0, sizeof(struct sockaddr_in));
    }

    // data
    struct iovec m_Iovec;
    // ���������ݻ����������ڻ������ͷ�
    // ���Ͳ������ݺ�m_Iovec.iov_base������ָ�������Ļ�����
    char *m_pCompleteBuffer;
    // ��ʶ���ݿ����������ģ������ݿ���Դ
    // ָ��Ķ��������new�����ģ�����Buffer�б��ͷ�
    DataContext *m_pContext;
    struct sockaddr_in m_UDPAddr;
};

/**
 * @brief �����շ�����������
 */
class BufferManager
{
  public:
    BufferManager();
    BufferManager(
        Reader *pReader,
        Writer *pWriter,
        ReadCallback *pReadCallback,
        WriteCallback *pWriteCallback,
        AppProtoSpec *pAppProtoSpec);
    virtual ~BufferManager();

    /**
     * @brief ʹ��Reader�������׽�������
     *
     * @return
     */
    int readUnxDmn();

    /**
     * @brief ʹ��Reader����TCP����
     *
     * @return
     */
    int readTCP();

    /**
     * @brief ʹ��Reader����UDP����
     *
     * @return
     */
    int readUDP();

    /**
     * @brief ʹ��Writer��������
     *
     * @return
     */
    int write();

    /**
     * @brief ������������д��Buffer��
     *
     * @param pBuf
     * @param len
     * @param pContext ָ��Ķ��������new������
     */
    void writeToBuffer(char *pBuf, size_t len, DataContext *pContext = NULL);
    void writeToBuffer(
        char *pBuf,
        size_t len,
        SocketAddress &addr,
        DataContext *pContext = NULL);

    int getSendBufferLength() const { return m_SendIovList.size(); }

    //
    // ����setϵ�к���������������new�����Ķ����ָ�룬���Ҳ����ͷ�
    //
    void setReader(Reader *pReader)
    {
        if (NULL != m_pReader) { delete m_pReader; }

        m_pReader = pReader;
    }

    void setWriter(Writer *pWriter)
    {
        if (NULL != m_pWriter) { delete m_pWriter; }

        m_pWriter = pWriter;
    }

    void setReadCallback(ReadCallback *pReadCallback)
    {
        if (NULL != m_pReadCallback) { delete m_pReadCallback; }

        m_pReadCallback = pReadCallback;
    }

    void setWriteCallback(WriteCallback *pWriteCallback)
    {
        if (NULL != m_pWriteCallback) { delete m_pWriteCallback; }

        m_pWriteCallback = pWriteCallback;
    }

    void setAppProtoSpec(AppProtoSpec *pAppProtoSpec)
    {
        if (NULL != m_pAppProtoSpec) { delete m_pAppProtoSpec; }

        m_pAppProtoSpec = pAppProtoSpec;
    }

    // 读取没有头部的TCP数据
    int readTCPWithoutHeader(uint32_t agentID);

  protected:
    void releaseSendBuffer();

    int readUnxDmnHeader();

    int readUnxDmnContent();

    int readTCPHeader();

    int readTCPContent();

  protected:
    // can't copy
    BufferManager(const BufferManager &buffer);
    BufferManager &operator=(const BufferManager &buffer);

  private:
    const int HTTPREADLENGTH = 1024;
    // ���ͻ�����
    std::list<Iov> m_SendIovList;

    // ������
    uint32_t m_nReadOffset;
    uint32_t m_nHeaderSize;
    uint32_t m_nContentLength;
    struct InReq m_inReq;
    char *m_pHeader;
    char *m_pContent;
    bool m_bReadHeader;
    bool m_bNewPackage; // �Ƿ񽫽����µ����ݰ�

    Reader *m_pReader;
    Writer *m_pWriter;
    ReadCallback *m_pReadCallback;
    WriteCallback *m_pWriteCallback;
    AppProtoSpec *m_pAppProtoSpec;
};

#endif // BUFFER_H_
